package com.apes.autoparts.supplier.todo;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.autoparts.supplier.contrast.ContrastService;
import com.apes.autoparts.supplier.platform.SupplierPlatformItem;
import com.apes.autoparts.supplier.platform.SupplierPlatformItemRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.generator.service.SequenceService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.jpa.spec.model.Group;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.mq.MQUtil;
import com.apes.framework.plugin.soe.store.database.repository.BusinessAttributeValueRepository;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.Tools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;


@Service("supplierPlatformTodoService")
public class SupplierPlatformTodoService extends DomainService {

    @Autowired
    private SupplierPlatformTodoCheckService todoCheckService;
    @Autowired
    private ContrastService contrastService;
    @Autowired
    private SupplierPlatformTodoRepository todoRepository;
    @Autowired
    private SupplierPlatformItemRepository supplierPlatformItemRepository;
    /***
     * 创建一个待办
     */
    public SupplierPlatformTodo insert(SimpleRequest request) {
        return todoCheckService.todoCheck(request);
    }

    /***
     * 处理一个待办
     */
    public SupplierPlatformTodo resolve(SimpleRequest request) {
        JSONObject param = request.getJO();

        SupplierPlatformTodo todo = todoRepository.findOne(param.getString("ID"));
        if (todo == null)
            throw new RuntimeException("通过流水码未找到对应的数据，流水码：" + param.getString("ID"));
        SupplierPlatformTodoParse todoParse = todo.getTodoParse();

        if (todoParse == null) {
            todoParse = new SupplierPlatformTodoParse();
            todoParse.setTodo(todo);
            todoParse.setId(SpringManager.getBean(SequenceService.class).getId(SupplierPlatformTodoParse.CONST_TABLE_NAME));
        }

        todoParse.setContrastPartCode(param.getString("CONTRAST_PART_CODE"));
        todoParse.setContrastOriginPlace(param.getString("CONTRAST_ORIGIN_PLACE"));

        if ( param.getString("BRAND_ID") != null) {
            todoParse.setContrastBrands(getBrand(param.getString("BRAND_ID")));
        }

        if (param.getString("CATEGORY_ID") != null){
            todoParse.setContrastCategories(getCategory(param.getString("CATEGORY_ID")));
        }


        todo.setTodoParse(todoParse);
        todo.setState("waitingConfirm");
        todo.setResolves(request.getJO().getJSONObject("resolves"));
        todo.setResolveDate(new Date());
        return todoRepository.save(todo);
    }




    /***
     * 更新供应商对照
     *
     */
    private void supplierContrast(List<SupplierPlatformTodo> todos) {
        SimpleRequest request = new SimpleRequest();
        if (todos.size() == 0)return;
        JSONObject param = new JSONObject();
        List<JSONObject> list= new ArrayList<>();
        String supplierPlatformItemId = todos.get(0).getSupplierPlatformItem().getId();
        List<String> sources = todos.stream().map(todo -> {
            return todo.getSource();
        }).collect(Collectors.toList());
        param.put("SUPPLIER_PLATFORM_ITEM_ID", supplierPlatformItemId);
        param.put("SUPPLIER_PLATFORM_SOURCES", sources);
        JSONArray jsonArray = contrastService.queryInsertBusinessInfos(param);
        Map map = new HashMap();
        // 转化成map对象,方便获取
        jsonArray.forEach(o -> {
            JSONObject item = (JSONObject) o;
            SupplierPlatformTodoParse todoParse = new SupplierPlatformTodoParse();
            map.put(item.getString("SUPPLIER_PLATFORM_SOURCE"), item);
        });

        for (SupplierPlatformTodo todo : todos) {
            list.add(todoCheckService.prepareModel(todo));
        }

        createBusinessInfo(map, list);
    }

    private void createBusinessInfo(Map map, List<JSONObject> list) {
        List createData = new ArrayList();
        List updateData = new ArrayList();
        for (JSONObject todo : list) {
            if (map.get(todo.get("SUPPLIER_PLATFORM_SOURCE")) != null) {
                todo.put("ID", ((JSONObject)map.get(todo.get("SUPPLIER_PLATFORM_SOURCE"))).getString("ID"));
                updateData.add(todo);
            } else {
                createData.add(todo);
            }
        }
        contrastService.createBusinessInfo(createData);
        contrastService.updateBusinessInfoContrast(updateData);
    }


    /***
     * 根据前端传入数据查询代办数据
     */
    public Page<SupplierPlatformTodo> findAll(SimpleRequest request) {

        Pageable pageable = JpaDsl.getPageable(request);

        Group group = getCondition(request.getJO().getJSONObject("condition"));

        Page<SupplierPlatformTodo> platformTodos = todoRepository.findAll(group.build(true), pageable);

        return platformTodos;
    }

    /***
     * 处理前端传入参数
     * 1. 对象统一取id字段，统一用equal
     * 2. 字符串统一用like
     */

    private Group getCondition(JSONObject condition) {
        Group group = new Group();

        condition.keySet().stream().forEach(key -> {

            String realKey = key.replace("#", ".");

            if (condition.get(key) == null) return;

            if (condition.get(key) instanceof String) {
                group.addFilters(JpaDsl.toFilter(
                        realKey, "LIKE", condition.get(key)));
            }

            if (condition.get(key) instanceof Map &&
                    condition.getJSONObject(key).getString("id") != null) {
                group.addFilters(JpaDsl.toFilter(
                        realKey, "LIKE", condition.getJSONObject(key).getString("id")));
            }

            if (condition.get(key) instanceof List &&
                    condition.getJSONArray(key).size() != 0) {

                ArrayList<String> arrayList = new ArrayList<>();

                condition.getJSONArray(key).stream().forEach(obj -> {

                    if (obj instanceof String) {
                        arrayList.add(obj.toString());
                    } else if (obj instanceof JSONObject) {
                        arrayList.add(((JSONObject) obj).getString("id"));
                    }

                });

                group.addFilters(JpaDsl.toFilter(
                        realKey, "IN", arrayList));
            }
        });

        return group;
    }

    private JSONObject getFrontCondition(JSONObject condition) {

        if (condition.getJSONObject("property#id") != null)
            condition.put("propertyId", condition.getJSONObject("property#id").getString("id"));
        if (condition.getJSONObject("supplierPlatformItem#supplier#id") != null)
            condition.put("supplierPlatformItemSupplierId" , condition.getJSONObject("supplierPlatformItem#supplier#id").getString("id"));
        if (condition.getJSONObject("todoParse#contrastBrand#id") != null)
            condition.put("contrastBrandId" , condition.getJSONObject("todoParse#contrastBrand#id").getString("id"));
        if (condition.getJSONObject("supplierPlatformItem#supplierPlatform#id") != null)
            condition.put("supplierPlatformItemSupplierPlatformId" , condition.getJSONObject("supplierPlatformItem#supplierPlatform#id").getString("id"));
        if (condition.getJSONObject("todoParse#contrastCategory#id") != null)
            condition.put("contrastCategoryId" , condition.getJSONObject("todoParse#contrastCategory#id").getString("id"));

        // 去除输入框位""情况
        if (condition.getString("id") != null && "".equals(condition.getString("id")))
            condition.remove("id");
        if (condition.getString("batch") != null && "".equals(condition.getString("batch")))
            condition.remove("batch");
        if (condition.getString("oldPartCode") != null && "".equals(condition.getString("oldPartCode")))
            condition.remove("oldPartCode");
        if (condition.getString("oldOriginPlace") != null && "".equals(condition.getString("oldOriginPlace")))
            condition.remove("oldOriginPlace");
        if (condition.getString("source") != null && "".equals(condition.getString("source")))
            condition.remove("source");
        return condition;
    }

    /***
     * 批量导入
     * 1. 查找原始数据
     * 2. 修改原始数据的编译数据
     */
    public List<Map> beImportTodo(SimpleRequest request) {
        String userId = request.get("userId") != null ? request.get("userId").toString() : "";
        String userName = request.get("userName") != null ?  request.get("userName").toString() : "";

        Map person = MapUtil.mapper("id", userId, "name", userName);
        Map map = (Map)invoke("mq.message.MQTotal", MapUtil.mapper("topic", "auto.supplierPlatformTodo.resolve"));
        if (Long.valueOf(map.get("total").toString()) > 0)
            throw new RuntimeException("稍后再导入数据,现存在" +map.get("total").toString() + "条数据待处理");
        JSONObject importData = request.get("importData");//Excel信息

        List<Map> todos = new ArrayList<>();                  //返回值
        importData.forEach((k, v) -> {

            JSONArray excl = (JSONArray) v;
            JSONArray header = (JSONArray) excl.get(0); //表格头部

            for (int i = 0; i < excl.size(); i++) {  //遍历每一行
                if (i == 0) continue; //跳过首行

                JSONArray lineData = (JSONArray) excl.get(i); //当前行
                if (lineData.size() == 0) continue;

                if (header.indexOf("流水码") == -1) throw new RuntimeException("请传入对应的内部流水码");
                if (lineData.get(header.indexOf("流水码")) == null) throw new RuntimeException("请传入对应的内部流水码，当前行号：" + i);


                Map m = MapUtil.mapper(
                        "ID", header.indexOf("流水码") < lineData.size() ? lineData.getString(header.indexOf("流水码")) : null,
                        "CONTRAST_PART_CODE", header.indexOf("对照零件编码") < lineData.size() ? lineData.getString(header.indexOf("对照零件编码")) : null,
                        "CONTRAST_ORIGIN_PLACE", header.indexOf("对照产地") < lineData.size() ? lineData.getString(header.indexOf("对照产地")) : null,
                        "BRAND_ID", header.indexOf("对照品牌") < lineData.size() ? lineData.getString(header.indexOf("对照品牌")) : null,
                        "CATEGORY_ID", header.indexOf("对照配件") < lineData.size() ? lineData.getString(header.indexOf("对照配件")) : null,
                        "resolves", MapUtil.mapper(
                                "id", person.get("id"),
                                "name",person.get("name")
                        ),
                        "resolveDate", new Date()
                );

//                request.setData(m);
                todos.add(m);
            }
        });
        return todos;
    }


    /***
     * 确认当前页
     * 1. 传入列表
     * 2. 切片处理
     */
    public List<Map> confirmCurrentPage(SimpleRequest request) {
        // 查询队列消息中存在的数据
        Map MQMap = (Map)invoke("mq.message.MQTotal", MapUtil.mapper("topic", "auto.supplierPlatformTodo.confirm"));
        if (Long.valueOf(MQMap.get("total").toString()) > 0)
            throw new RuntimeException("稍后再确认数据,现存在" +MQMap.get("total").toString() + "条数据待处理");

        JSONArray array = request.getJA();
        Map person = MapUtil.mapped(request.getPerson());
        List<Map> list = array.stream().map(obj -> {
            JSONObject json = (JSONObject) obj;
            return MapUtil.mapper(
                    "id", json.getString("id"),
                    "confirmId", MapUtil.mapper(
                            "id", person.get("id"),
                            "name", person.get("name")
                    ),
                    "confirmDate", new Date(),
                    "source", json.getString("source")
            );
        }).collect(Collectors.toList());
        // 查询不在当前页的待确认状态数据有无相同的代办
        List<String> sources = todoRepository.findTodoByPage(
                array.stream().map(obj -> {
                    JSONObject json = (JSONObject) obj;
                    return json.getString("id");
                }).collect(Collectors.toList())
                ,
                array.stream().map(obj -> {
                    JSONObject json = (JSONObject) obj;
                    return json.getString("source");
                }).collect(Collectors.toList())
        );

        // 去除待处理状态的数据
        List<Map> collect = list.stream().filter(
                map -> {
                    String source = map.get("source").toString();
                    if (sources.indexOf(source) >= 0) return false;
                    int size = todoRepository.findAll(JpaDsl.toCriteria("source", "EQ", source, "state", "EQ", "waitingResolve")).size();
                    return size == 0;}).
                collect(Collectors.toList());

        // 排序
        collect.sort(Comparator.comparing((Map h) -> ((String) h.get("id")))); //正序
        return collect;
    }

    /***
     * 确认所有
     * 1. 传入条件
     * 2. 切片处理
     */
    public JSONObject confirmAll(SimpleRequest request) {
        // 查询队列消息中存在待处理的数据
        Map map = (Map)invoke("mq.message.MQTotal", MapUtil.mapper("topic", "auto.supplierPlatformTodo.confirms"));
        if (Long.valueOf(map.get("total").toString()) > 0)
            throw new RuntimeException("稍后再确认数据,现存在" +map.get("total").toString() + "条数据待处理");
        String userId = request.getJO().getString("userId");
        String userName = request.getJO().getString("userName");
        JSONObject frontCondition = getFrontCondition(request.getJO());
        Map person = MapUtil.mapper("id", userId,"name", userName);
        int size = 500;
        frontCondition.put("PAGE", 0);
        frontCondition.put("SIZE", size);
        JSONArray array = SpringManager.getBean(SupplierPlatformTodoDao.class).findTodoTotal(frontCondition);
        String maxID = "";
        if ( array.size() != 0 )
            while (true) {
                JSONArray todos = SpringManager.getBean(SupplierPlatformTodoDao.class).findTodoPage(frontCondition);
                List<Map> list = todos.stream().map(o -> {
                    JSONObject json = (JSONObject) o;
                    return MapUtil.mapper(
                            "id", json.getString("ID"),
                            "confirmId", MapUtil.mapper(
                                    "id", person.get("id"),
                                    "name", person.get("name")
                            ),
                            "source", json.getString("SOURCE"),
                            "confirmDate", new Date(),
                            "supplierPlatformItem", json.getString("SUPPLIER_PLATFORM_ITEM_ID")
                    );
                }).collect(Collectors.toList());
//                SpringManager.getBean(DomainService.class).invoke("auto.supplierPlatformTodo.confirms", list);
                MQUtil.publish("auto.supplierPlatformTodo.confirms", "待办确认", list);
                if (todos.size() < size)
                    break;
                maxID = list.get(list.size() - 1).get("id").toString();
                frontCondition.put("maxID", maxID);
            }

        return new JSONObject();
    }
    /***
     * 消息队列
     * 确认一些待办
     */
    public void confirms(SimpleRequest request) {
        JSONArray array = request.getJA();
        List<String> todoIds = array.parallelStream().map(o -> {
            JSONObject json = (JSONObject) o;
            return json.getString("id");
        }).collect(Collectors.toList());
        List<SupplierPlatformTodo> todos = todoRepository.findAllById(todoIds);
        supplierContrast(todos);
        List<SupplierPlatformTodo> confirm = todos.stream().map(todo -> {
            todo.setConfirmId(request.getPerson());
            todo.setConfirmDate(new Date());
            todo.setState("confirm");
            return todo;
        }).collect(Collectors.toList());
        todoRepository.save(confirm);
    }

    private List<String> getTodo(List<Map> list) {
        List<String> WaitingResolveSources = new ArrayList<>();
        Map<Object, List<Map>> supplierPlatformItem = list.stream().collect(Collectors.groupingBy(v -> {
            return v.get("supplierPlatformItem");
        }));
        Set<Object> keySet = supplierPlatformItem.keySet();
        for (Object o: keySet){
            for (int i= 0; i <= list.size() / 800; i++) {
                List<Map> sp = list.subList(i * 800, i == (list.size() /800) ? list.size() : (i + 1) * 800);

                List<String> WaitingResolveSource = todoRepository.findTodoByWaitingResolve(
                        sp.stream().map(obj -> {
                            Map map = (HashMap) obj;
                            return map.get("id").toString();
                        }).collect(Collectors.toList())
                        ,
                        sp.stream().map(obj -> {
                            Map map = (HashMap) obj;
                            return map.get("source").toString();
                        }).collect(Collectors.toList())
                        ,o.toString()
                );
                WaitingResolveSources.addAll(WaitingResolveSource);
            }
        }

        return WaitingResolveSources;
    }

    // 获取 不在本次待确认中，供应商
    private List<String> getWaitingConfirm(List<Map> list) {

        Map map = new HashMap();
        List<String> newSources = new ArrayList<>();

        list.stream().collect(Collectors.groupingBy(v -> {
            return v.get("supplierPlatformItem");
        })).forEach( (key, value) -> {
            map.put(key, value.stream().
                    collect(Collectors.groupingBy(v -> {
                        return v.get("source");
                    })).entrySet().stream().map(e -> e.getValue()).collect(Collectors.toList()));
        });
        Set keySet = map.keySet();
        for (Object o : keySet) {
            List supplierPlatformItemList = (List)map.get(o);
            for (int i= 0; i <= supplierPlatformItemList.size() / 400; i++) {
                List<List<Map>> sp = supplierPlatformItemList.subList(i * 400, i == (supplierPlatformItemList.size() /400) ? supplierPlatformItemList.size() : (i + 1) * 400);
                List<String> ids = new ArrayList<>();
                List<String> sources = new ArrayList<>();
                for (List<Map> l:sp) {
                    for (Map k : l){
                        ids.add(k.get("id").toString());
                    }
                }
                for (List<Map> l:sp) {
                    for (Map k : l){
                        sources.add(k.get("source").toString());
                    }
                }
                List<String> waitingConfirm = todoRepository.findTodoByWaitingConfirm(ids, sources, o.toString());
                newSources.addAll(waitingConfirm);
            }
        }
        return newSources;
    }


    public void inserts(SimpleRequest request) {
        todoCheckService.todoChecks(request);
    }

    public void createTodos(SimpleRequest request) {
        JSONObject jo = request.getJO();
        if( !"create".equals(jo.getString("property"))) return;
        List<SupplierPlatformTodo> todos= JSONArray.parseArray(jo.getJSONArray("data").toString(), SupplierPlatformTodo.class);
        if (todos.size() == 0) return;
        for (SupplierPlatformTodo todo : todos) {
            todo.setProperty(SpringManager.getBean(BusinessAttributeValueRepository.class).findOne("Todo.property.create"));
            SupplierPlatformTodoParse todoParse = todo.getTodoParse();
            if (todoParse != null) {
                Object brandId = todo.getTodoParse().getContrastBrands().get("id");
                Map brand = brandId != null ? getBrand(brandId.toString()) : null;
                todoParse.setContrastBrands(brand);
                Object CategoryId = todo.getTodoParse().getContrastCategories().get("id");
                Map category = CategoryId != null ? getCategory(CategoryId.toString()) : null;
                todoParse.setContrastCategories(category);
                todo.setState("waitingConfirm");
            } else {
                todo.setState("waitingResolve");
            }
        }
        SupplierPlatformItem one = supplierPlatformItemRepository.findOne(todos.get(0).getSupplierPlatformItem().getId());

        List<SupplierPlatformTodo> save = todoRepository.save(todos);
        List<Map> list = save.stream().map(todo -> {
            return MapUtil.mapper(
                    "id", todo.getId(),
                    "source", todo.getSource(),
                    "confirmDate", new Date(),
                    "remark","数据中心数据，系统自动确认",
                    "supplierPlatformItem", todo.getSupplierPlatformItem().getId()
            );
        }).collect(Collectors.toList());

        MQUtil.publish("auto.supplierPlatformTodo.confirms", "数据中心自动确认", list);
    }

    private Map getBrand(String brandId) {
        Object invoke = null;
        try {
            invoke = invoke("cm.dataCenter.brand.findOne", MapUtil.mapper("id", brandId));
        } catch (Exception e) {
            throw new RuntimeException(Tools.getAllStackTrace(e));
        }
        Map map = invoke != null ? MapUtil.mapped(invoke) : null;
        if (map == null) return new HashMap();
        return MapUtil.mapper("id", map.get("id"), "name", map.get("name"));
    }

    private Map getCategory(String categoryId) {
        Object invoke;
        try {
            invoke = invoke("cm.dataCenter.category.findOne", MapUtil.mapper("id", categoryId));
        } catch (Exception e) {
            throw new RuntimeException("111");
        }
        Map map = invoke != null ? MapUtil.mapped(invoke) : null;
        if (map == null) return new HashMap();
        return MapUtil.mapper("id", map.get("id"), "name", map.get("name"));
    }
}
